﻿using System;
using System.Net;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using DXTools.UI.Core.ViewModel;

namespace DXTools.UI.Modules.ODataQueryDesigner.Model
{
    public class EntityClass :ViewModelBase
    {
        public EntityClass()
        {
            this.Attributes = new ObservableCollection<AttributeClass>();
            this.SortByAttributes = new ObservableCollection<AttributeClass>();
            this.FilterAttributes = new ObservableCollection<AttributeClass>();
            this.Filters = new ObservableCollection<FilterClass>();
            this.Relationships_OneToMany = new ObservableCollection<RelationshipClass>();
            this.Relationships_ManyToOne = new ObservableCollection<RelationshipClass>();
            this.Relationships_ManyToMany = new ObservableCollection<RelationshipClass>();
            InitialiseEvents();
        }            

        public EntityClass(String SchemaNameSet, String LogicalName)
        {
            this.SchemaNameSet = SchemaNameSet;
            this.LogicalName = LogicalName;
            this.Attributes = new ObservableCollection<AttributeClass>();
            this.SortByAttributes = new ObservableCollection<AttributeClass>();
            this.FilterAttributes = new ObservableCollection<AttributeClass>();
            this.Filters = new ObservableCollection<FilterClass>();
            this.Relationships_OneToMany = new ObservableCollection<RelationshipClass>();
            this.Relationships_ManyToOne = new ObservableCollection<RelationshipClass>();
            this.Relationships_ManyToMany = new ObservableCollection<RelationshipClass>();
            InitialiseEvents();
            
        }

        public string SchemaNameSet { get; set; }
        public string LogicalName { get; set; }
        private bool _isSelectAllAttributes;

        private ObservableCollection<AttributeClass> _attributes; 
        private ObservableCollection<AttributeClass> _sortByAttributes;
        private ObservableCollection<AttributeClass> _filterAttributes;
        private ObservableCollection<RelationshipClass> _relationships_OneToMany;
        private ObservableCollection<RelationshipClass> _relationships_ManyToOne;
        private ObservableCollection<RelationshipClass> _relationships_ManyToMany;
        private ObservableCollection<FilterClass> _filters;

        public List<List<FilterClass>> FilterGroups { get; set; }


        public event EventHandler AllAttributesSelectedEvent; // Denotes when Select all is selected
        public event EventHandler AllAttributesUnSelectedEvent; // Denotes when Select All is unselected
        public event EventHandler AnyAttributeUnSelectedEvent; // Denotes when any attribute is unselected

        private void InitialiseEvents()
        {
            //
            // Initialise Attribute selected events
            //
            _attributes.CollectionChanged += ((o, a) =>
            {
                NotifyCollectionChangedEventArgs args = (NotifyCollectionChangedEventArgs)a;

                if (args.Action == NotifyCollectionChangedAction.Add)
                {
                    AttributeClass item = (AttributeClass)args.NewItems[0];
                    item.IsAnyUnSelectedEvent += new EventHandler(this.UnSelectAnyAttribute);
                    item.IsSelectAllEvent += new EventHandler(this.SelectAllAttributes);
                    item.IsUnSelectAllEvent += new EventHandler(this.SelectAllAttributes);
                }
            });

            //
            // Initialise Filter Attribute selected events
            //
            _filters.CollectionChanged += ((o, a) =>
            {
                NotifyCollectionChangedEventArgs args = (NotifyCollectionChangedEventArgs)a;

                if (args.Action == NotifyCollectionChangedAction.Add)
                {
                    FilterClass item = (FilterClass)args.NewItems[0];
                    item.FilterAttributeSelectedEvent += new EventHandler(this.FilterAttributeSelected);
                    item.DeleteFilterEvent += new EventHandler(this.DeleteFilterRow);
                    item.UnGroupFiltersEvent += new EventHandler(this.UngroupFilters);
                }
            });



        }

        /// <summary>
        /// Performs action to add new Filter item row when last added filter row attribute selected
        /// </summary>
        /// <param name="source"></param>
        /// <param name="args"></param>
        public void FilterAttributeSelected(object source, EventArgs args)
        {
            if (source != null)
            {
                FilterClass item = (FilterClass)source;
                //
                // Add next filter but limit to 6 only
                if (this._filterAttributes.Count > 0 && Filters.Count < 6 && item == _filters[_filters.Count - 1])
                {
                    FilterClass filter = new FilterClass();
                    filter.Attributes = new AttributeClass[_filterAttributes.Count];
                    _filterAttributes.CopyTo(filter.Attributes, 0);
                    Filters.Add(filter);
                    RaisePropertyChanged("Filters");
                    
                }
            }
        }

        /// <summary>
        /// Performs action to add new Filter item row when last added filter row attribute selected
        /// </summary>
        /// <param name="source"></param>
        /// <param name="args"></param>
        public void DeleteFilterRow(object source, EventArgs args)
        {
            if (source != null)
            {
                FilterClass item = (FilterClass)source;
                Filters.Remove(item);
                RaisePropertyChanged("Filters");
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="args"></param>
        public void UngroupFilters(object source, EventArgs args)
        {
            if (source != null)
            {

                FilterClass item = (FilterClass)source;
                List<FilterClass> tmpFilterGroup = null;

                foreach (List<FilterClass> group in FilterGroups)
                {
                    if (group[0] == item)
                    {
                        foreach (FilterClass filter in group)
                        {
                            filter.IsPrimaryGroupAttribute = false;
                            filter.IsFinalGroupAttribute = false;
                            filter.GroupLogicalOperator = null;
                        }
                        tmpFilterGroup = group;
                        break;
                    }
                }
                if (tmpFilterGroup != null)
                {
                    FilterGroups.Remove(tmpFilterGroup);
                    RaisePropertyChanged("Filters");
                }
            }
        }

        /// <summary>
        /// Handles when any Attribute is unselected, except (Select All)
        /// </summary>
        /// <param name="source"></param>
        /// <param name="args"></param>
        public void UnSelectAnyAttribute(object source, EventArgs args)
        {
            if (IsSelectAllAttributes == true)
            {
                IsSelectAllAttributes = false;
                AnyAttributeUnSelectedEvent(this, null);
            }
        }

        /// <summary>
        /// Handles when (Select All) attributes is selected
        /// </summary>
        /// <param name="source"></param>
        /// <param name="args"></param>
        public void SelectAllAttributes(object source, EventArgs args)
        {
            if (IsSelectAllAttributes == false)
            {
                IsSelectAllAttributes = true;
                AllAttributesSelectedEvent(this, null);
            }
            else
            {
                IsSelectAllAttributes = false;
                AllAttributesUnSelectedEvent(this, null);
            }
        }


        public bool IsSelectAllAttributes
        {
            get { return _isSelectAllAttributes; }
            set { if (_isSelectAllAttributes != value) { _isSelectAllAttributes = value; RaisePropertyChanged("IsSelectAllAttributes"); } }
        }

        public ObservableCollection<AttributeClass> Attributes
        {
            get { return _attributes; }
            set { if (_attributes != value) { _attributes = value; RaisePropertyChanged("Attributes"); } }
        }
        public ObservableCollection<AttributeClass> SortByAttributes
        {
            get { return _sortByAttributes; }
            set { if (_sortByAttributes != value) { _sortByAttributes = value; RaisePropertyChanged("SortByAttributes"); } }
        }
        public ObservableCollection<AttributeClass> FilterAttributes
        {
            get { return _filterAttributes; }
            set { if (_filterAttributes != value) { _filterAttributes = value; RaisePropertyChanged("FilterAttributes"); } }
        }
        public ObservableCollection<FilterClass> Filters
        {
            get { return _filters; }
            set { if (_filters != value) { _filters = value; RaisePropertyChanged("Filters"); } }
        }
        public ObservableCollection<RelationshipClass> Relationships_OneToMany
        {
            get { return _relationships_OneToMany; }
            set { if (_relationships_OneToMany != value) { _relationships_OneToMany = value; RaisePropertyChanged("Relationships_OneToMany"); } }
        }

        public ObservableCollection<RelationshipClass> Relationships_ManyToOne
        {
            get { return _relationships_ManyToOne; }
            set { if (_relationships_ManyToOne != value) { _relationships_ManyToOne = value; RaisePropertyChanged("Relationships_ManyToOne"); } }
        }

        public ObservableCollection<RelationshipClass> Relationships_ManyToMany
        {
            get { return _relationships_ManyToMany; }
            set { if (_relationships_ManyToMany != value) { _relationships_ManyToMany = value; RaisePropertyChanged("Relationships_ManyToMany"); } }
        }    

           

        }
}
